package com.dh.spring.client.bootstrap;

import com.dh.spring.client.handler.ChannelHandler;
import com.dh.spring.common.BasicConstant;
import com.dh.spring.select.MainClientSelector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Map;
import java.util.concurrent.*;

public class GlobalNIOClientBootstrap {
    private static final Logger logger = LoggerFactory.getLogger(GlobalNIOClientBootstrap.class);

    /**
     * map : [channelName <-----> ChannelHandler] 待下载文件对应通道与该通道处理器
     * */
    public static Map<String, ChannelHandler> channelHandlerMaps = new ConcurrentHashMap<>();
    public final static ThreadPoolExecutor executorService = new ThreadPoolExecutor(
        Runtime.getRuntime().availableProcessors(),
        Runtime.getRuntime().availableProcessors() + 2,
        1000,
        TimeUnit.MILLISECONDS,
        new LinkedBlockingQueue<>(100),
        Executors.defaultThreadFactory());
    /**
     * map : [SelectionKey <-----> FileChannel] 待下载文件对应通道选择键与文件通道，从该选择键读取流数据通过FileChannel写入文件
     * */
    public static final Map<SelectionKey ,FileChannel> fileChannelsMap = new ConcurrentHashMap<>();
    public volatile static Selector selector = null;

    public static Selector open() {
        try {
            if(null == selector)
                selector = Selector.open();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return selector;
    }

    //TODO 通道处理工厂启动所有通道处理任务
    public static void start() {

        //TODO 注册通道核心服务,向selector注册OP_ACCEPT事件(ServerSocketChannelHttpRequestHandler监听客户端http请求)
        channelHandlerMaps.put(BasicConstant.REQUEST_CHANNEL_SERVER, new ServerSocketChannelHttpRequestHandler(BasicConstant.REQUEST_CHANNEL_SERVER));

        //TODO --> 文件核心服务Handler
        channelHandlerMaps.put(BasicConstant.FILE_CORE_SERVICE_HANDLER, new FileCoreServiceHandler());

        //TODO 开启Selector选择器监听(监听客户端http请求和文件上传下载socket请求)
        new Thread(new MainClientSelector(), "Main Selector [Reactor Thread]").start();
    }

    public static ChannelHandler getHandler(String serverName) {
        return channelHandlerMaps.get(serverName);
    }
}
